using System;
using System.Globalization;
using System.Net.Mail;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using ICalendar.CalendarProperties;

namespace ICalendar.CalendarProperties
{
    /// <summary>
    /// The property defines the organizer for a calendar component.
    /// </summary>
    [Serializable]
    [XmlRoot("organizer")]    
    public class Organizer : CalendarPropertyBase<MailAddress> 
    {
        private static readonly string[] reservedNames = new[] { "SENT-BY", ReservedNames.ParameterCommonName, "DIR", ReservedNames.ParameterLanguage };
        
        #region Properties
        public MailAddress SentBy { get; set; }
        /// <summary>
        /// and DIR, to indicate the URI that points to the directory information corresponding to the attendee
        /// </summary>
        public Uri DirectoryEntryReference { get; set; }
        /// <summary>
        /// If the LANGUAGE property parameter is specified, the identified language applies to the CN parameter.
        /// </summary>
        public CultureInfo Language { get; set; }
        /// <summary>
        /// 
        /// </summary>
        //public Dictionary<string, string> CustomXParameters { get; set; }
        #endregion

        private Organizer()
        {
            
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="mailAddress">This value type is used to identify properties that contain a calendar user address. </param> 
        public Organizer(MailAddress mailAddress):this(mailAddress,null)
        {            
          
        }

        public Organizer(string mail) : this(new MailAddress(mail),null)
        {
        }

        public Organizer(MailAddress mailAddress,  MailAddress sentBy)
        {
            if (mailAddress == null)
            {
                throw new ArgumentNullException("mailAddress");
            }

            this.Value = mailAddress;
            this.SentBy = sentBy;
            this.Language = CultureInfo.CurrentCulture;
        }

        protected Organizer(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            this.Value = Util.FromCalAddressAndCommonName(info.GetString("ATTENDEE"), info.GetString(ReservedNames.ParameterCommonName));            
            this.SentBy = info.GetString("SENT-BY").FromCalAddress();
            var tempDIR = info.GetString("DIR");
            if (tempDIR != null)
            {
                this.DirectoryEntryReference = new Uri(tempDIR.Replace("\"", ""));
            }
            this.Language = CultureInfo.GetCultureInfo(info.GetString(ReservedNames.ParameterLanguage));
        }

        //public new string ToString()
        //{
        //    //The value can be A URI, but now i'll use just a MailAddress Uri type            
        //    return Util.Write("ATTENDEE", GetValue(), GetXParameters());
        //}

        protected override void SetParametersFromXParameters(XParameterCollection xparams)
        {
            if (xparams == null)
                return;

            this.Value = Util.FromCalAddressAndCommonName(GetValue(), xparams.GetValue(ReservedNames.ParameterCommonName));
            this.SentBy = xparams.GetValue("SENT-BY").FromCalAddress();
            var tempDIR = xparams.GetValue("DIR");
            if (tempDIR != null)
            {
                this.DirectoryEntryReference = new Uri(tempDIR.Replace("\"", ""));
            }

            var language = xparams.GetValue(ReservedNames.ParameterLanguage);
            if (language != null)
            {
                this.Language = CultureInfo.GetCultureInfo(language);
            }
        }

        protected override XParameterCollection GetXParametersFromParameters()
        {
            return new XParameterCollection
                       {
                           {"SENT-BY", string.Format("\"{0}\"", this.SentBy.GetCalAddress())},
                           {ReservedNames.ParameterCommonName, this.Value.GetCommonName()},
                           {"DIR", string.Format("\"{0}\"", this.DirectoryEntryReference)},
                           {ReservedNames.ParameterLanguage, Language.Name}
                       };         
        }

        protected override string[] GetXReservedParametersNames()
        {
            return reservedNames;
        }

        protected override void SetValue(string value)
        {            
            this.Value = value.Replace("mailto:", "").FromCalAddress();
        }

        protected override string GetValue()
        {
            return Value.GetCalAddress();
        }

        public static implicit operator Organizer(MailAddress mailAddress)
        {
            return new Organizer(mailAddress);
        }


        #region ISerializable Members

        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            info.AddValue("SENT-BY", string.Format("\"{0}\"", this.SentBy.GetCalAddress()));
            info.AddValue(ReservedNames.ParameterCommonName, this.Value.GetCommonName());
            info.AddValue("DIR", string.Format("\"{0}\"", this.DirectoryEntryReference));
            info.AddValue(ReservedNames.ParameterLanguage, Language.Name);
        }

        #endregion
    }
}